dojo.provide("xray.DataStore");

dojo.require("dijit.Dialog");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dojo.require("dijit.form.Textarea");
dojo.require("dijit.form.ValidationTextBox");
dojo.require("dijit.form.Button");
dojo.require("dijit.form.CheckBox");
dojo.require("dojo.date.locale");
dojo.require("dojo.data.ItemFileWriteStore");

dojo.registerModulePath("xray.images", "../../images");
dojo.requireLocalization("xray", "DataStore");


dojo.declare("xray.DataStore", dijit._Widget, {
	sqlLiteDb: "xRay.db",

	contentSave: "<fieldset>"+
					'<legend>${saveSession}</legend>'+
					'<p><label>${userName}</label><input required="required" type="text" class="inputDialog" name="author" dojoType="dijit.form.ValidationTextBox"></p>'+
					'<p><label>${comment}</label><input type="text" class="inputDialogComment" name="comment" dojoType="dijit.form.Textarea"></p>'+
					'<p><input type="radio" name="${id}_fileType" id="${id}_file" value="file" class="inputDialogComment" dojoType="dijit.form.RadioButton"><label for="${id}_file">${file}</label> <input type="radio" value="db" id="${id}_db" class="inputDialogComment" name="${id}_fileType" dojoType="dijit.form.RadioButton" checked="checked" ><label for="${id}_db">${internally}</label></p>'+
					'<p><span id="${id}_saveSession"><img src="${iconSave}" class="formSubmit" /></span> <span id="${id}_cancelSessionSave"><img src="${iconCancel}" class="formSubmit"></span></p>'+
				'</fieldset>',
	
	contentConfirmDelete: '<fieldset>'+
						'<legend>${confirmDelete}</legend>'+
						'<p><span id="${id}_deleteSession"><img src="${iconDelete}" class="formSubmit"></span> <span id="${id}_cancelSessionDelete"><img src="${iconCancelDelete}" class="formSubmit"></span></p>'+
					'</fieldset>',
	
	gridNode: "xrayGrid",
	dataSource: null,
	
	postCreate: function(){
		// load i18n
		this.messages = dojo.i18n.getLocalization("xray", "DataStore", this.lang);
		this.messages.id = this.id;
		
		// connect to SQLLite
		this.connect().addCallback(dojo.hitch(this, function(e){
			if (this.updateDb){
				this.dropDb();
			}

			// always attempt to create the database
			this.createDb().addCallback(dojo.hitch(this, function(){
				this.loadItems();
			}));
		})).addErrback(dojo.hitch(this, function(e){
			// report error
		}));
		
		// initialize grid
		this.initGrid();
		
		// initialize dialog for saving and confirmation messages
		this.dialogSave = new xray.Dialog({
			draggable: false, 
			titleBar: false, 
			content: dojo.string.substitute(this.contentSave, this.messages),
		});
		this.dialogSave.startup();
		
		this.dialogDeleteConfirm = new xray.Dialog({
			draggable: false, 
			titleBar: false, 
			content: dojo.string.substitute(this.contentConfirmDelete, this.messages)
		});
		this.dialogDeleteConfirm.startup();
		
		// connect to dialog buttons
		dojo.connect(dojo.byId(this.id+"_saveSession"), "onclick", this, function(e){
			e.preventDefault(); 
			this.addItem();
		});
		
		dojo.connect(dojo.byId(this.id+"_cancelSessionSave"), "onclick", this, function(e){
			e.preventDefault(); 
			this.dialogSave.hide();
		});
		
		dojo.connect(dojo.byId(this.id+"_deleteSession"), "onclick", this, function(e){
			e.preventDefault(); 	
			this.deleteItem();
		});
		
		dojo.connect(dojo.byId(this.id+"_cancelSessionDelete"), "onclick", this, function(e){
			e.preventDefault(); 
			this.dialogDeleteConfirm.hide();
		});
	},
	
	// connects to SQLLite ressource
	connect: function(){
		var d = new dojo.Deferred();
		
		// connect to SQLLite
		this.conn = new air.SQLConnection(); 
		
		// event handling
		this.conn.addEventListener(air.SQLEvent.OPEN, function(e){
			d.callback(e);
		}); 
		this.conn.addEventListener(air.SQLErrorEvent.ERROR, function(e){
			d.errback(e);
		}); 
		
		// reference to db file, if not available it will be created automatically
		var dbFile = air.File.applicationStorageDirectory.resolvePath(this.sqlLiteDb); 
		this.conn.openAsync(dbFile); 
		
		return d;
	},
	
	// initializes datagrid
	initGrid: function(){
		// create grid to display data
		this.sessionStore = new dojo.data.ItemFileWriteStore({id: "sessionStore", data: {identifier: 'id', items: []}});

		var layout = [[
			{name: this.messages.gridId, field: 'id', width: "5%"},
			{name: this.messages.gridAuthor, field: 'author', width: "25%"},
			{name: this.messages.gridComment, field: 'comment', width: "auto"},
			{name: this.messages.gridCreated, field: 'created', width: "25%"},
			{name: this.messages.gridEdit, field: 'edit', width: "110px"}
		]];
		
		this.grid = new xray.Grid({title: "History", store: this.sessionStore, structure: layout, rowsPerPage: 10, id: "sessionGrid"}, dojo.doc.createElement("div"));
		dijit.byId("mainTabs").addChild(this.grid);
		this.grid.startup();
		
		// connecting to grid events
		// loading, editing
		dojo.connect(this.grid, "onCellClick", this, function(e){
			var selected = this.grid.selection.getSelected();
			var id = this.sessionStore.getValue(selected[0], "id");

			if (e.target.className == 'loadSession'){
				this.loadSession(id);
			}else if (e.target.className == 'deleteSession'){
				this.currentId = id;
				this.dialogDeleteConfirm.show();
			}
		});
	},
	
	// add new session item
	addItem: function(){
		if (!this.dialogSave.validate()){
			return;
		}
		var formData = this.dialogSave.attr("value");
		formData.created = new Date();
		
		if (formData[this.id+"_fileType"] == "file"){
			this._saveToFile(formData);
		}else{
			this._saveToDb(formData);	
		}
	},
	
	_saveToFile: function(formData){
		this.docsDir = air.File.desktopDirectory.resolvePath(dojo.date.locale.format(new Date(formData.created), {datePattern: "yyyy-MM-dd", timePattern: "HH-mm"})+" xRay session.xry");
		this.docsDir.browseForSave(this.messages.saveAs);
		this.docsDir.addEventListener(air.Event.SELECT, dojo.hitch(this, "_writeData", formData));
	},
	
	_writeData: function(formData, e){
		// file dialog to create file name
		this.docsDir.removeEventListener(air.Event.SELECT, dojo.hitch(this, "_writeData", formData));

		var tmpArr = air.File(e.target).nativePath.split(air.File.separator);
		var fileName = tmpArr.pop();//remove last array item and return its content

		// in the case we don't provide an extension or wrong type we change file to correct extension
		var saveFilename = this._checkExtension(fileName);
		tmpArr.push(saveFilename);

		// create new file object
		var file = new air.File(tmpArr.join(air.File.separator));

		// save to stream
		var stream = new air.FileStream();
		stream.open( file, air.FileMode.WRITE );
		stream.writeMultiByte( dojo.toJson(this._createData(formData)), air.File.systemCharset );
		stream.close();
		
		this.dialogSave.hide();
	},
	
	_checkExtension: function(file){
		var extension = file.split(".")[1];
		if (extension == "xry"){
			return file;
		}
		return file.split(".")[0] + ".xry";
	},
	
	// creates an object to be saved in database or other storage mediums
	_createData: function(data){
		var returnData = [{
			author: data.author, 
			comment: data.comment,
			stats_data: this.dataSource.get(),
			created: dojo.date.locale.format(new Date(data.created), {datePattern: "yyyy-MM-dd", timePattern: "HH:mm:ss"})
		}]; 
		
		return returnData;
	},
	
	_saveToDb: function(formData){
		var stmt = new air.SQLStatement();
		stmt.addEventListener(air.SQLErrorEvent.ERROR, function(){
			this.dialogSave.hide();
		});
		
		stmt.addEventListener(air.SQLEvent.RESULT, dojo.hitch(this, function(){
			var result = stmt.getResult();
			
			var item = this._createData(formData);
			dojo.mixin(item, {
				id: result.lastInsertRowID, 
				edit: "<img src='"+this.messages.gridLoadSession+"' class='loadSession' /> <img src='"+this.messages.gridDeleteSession+"' class='deleteSession' />"
			});
			
			this.sessionStore.newItem(item);
			this.sessionStore.save();
			
			this.dialogSave.hide();
		}));
		
		stmt.sqlConnection = this.conn;
		stmt.text = 'INSERT INTO xRaySessions ('+
					'stats_data, '+
					'comment, '+
					'author, '+
					'created ) VALUES ("'+
					dojo.toJson(this.sessionData)+'",'+
					'"'+formData.comment+'",'+
					'"'+formData.author+'",'+
					'"'+dojo.date.locale.format(new Date(formData.created), {datePattern: "yyyy-MM-dd", timePattern: "HH:mm:ss"})+'"'+
					')';

		stmt.execute();
	},
	
	// delete session item
	deleteItem: function(){
		if (!this.currentId){
			return;
		}
		
		var stmt = new air.SQLStatement();
		
		stmt.addEventListener(air.SQLErrorEvent.ERROR, function(e){
			
		});
		var currentId = this.currentId;
		stmt.addEventListener(air.SQLEvent.RESULT, dojo.hitch(this, function(e){
			var result = stmt.getResult();
			
			this.sessionStore.fetchItemByIdentity({
			  	identity: currentId, 
			  	onItem: dojo.hitch(this, function(item){
			    	this.sessionStore.deleteItem(item);
			  	})
			});
			console.log("deleted Item");
			this.dialogDeleteConfirm.hide();
		}));
		
		stmt.sqlConnection = this.conn;
		stmt.text = 'DELETE FROM xRaySessions WHERE id = "'+this.currentId+'";';
		this.currentId = null;
		
		stmt.execute();
	},
	
	// TODO: implement updating of session
	updateItem: function(){
		
	},
	
	// loading of session item
	loadItem: function(id){
		var stmt = new air.SQLStatement();
		stmt.addEventListener(air.SQLErrorEvent.ERROR, function(){
			
		});
		stmt.addEventListener(air.SQLEvent.RESULT, function(){
			
		});
		
		stmt.sqlConnection = this.conn;
		stmt.text = 'SELECT * FROM xRaySessions WHERE id = "'+id+'";';
		
		stmt.execute();
	},
	
	// loading of all items available
	loadItems: function(){
		var stmt = new air.SQLStatement();
		
		stmt.addEventListener(air.SQLErrorEvent.ERROR, function(e){
			this._errback(e);
		});
		
		stmt.addEventListener(air.SQLEvent.RESULT, dojo.hitch(this, function(e){
			var sessionData = stmt.getResult();

			// no records available
			if (!sessionData.data){
				return;
			}

			for (var i = 0; i<sessionData.data.length; i++){
				var item = {
					id: sessionData.data[i].id, 
					author: sessionData.data[i].author, 
					comment: sessionData.data[i].comment, 
					created: dojo.date.locale.format(new Date(sessionData.data[i].created), {datePattern: "yyyy-MM-dd", timePattern: "HH:mm:ss"}), 
					edit: "<img src='"+this.messages.gridLoadSession+"' class='loadSession' /> <img src='"+this.messages.gridDeleteSession+"' class='deleteSession' />"
				};
				this.sessionStore.newItem(item);
				this.sessionStore.save();
			}
		}));
		
		stmt.sqlConnection = this.conn;
		stmt.text = 'SELECT * FROM xRaySessions';

		stmt.execute();
	},
	
	// public 
	saveSession: function(){
		this.dialogSave.show();
	},
	
	loadSession: function(id){
		console.log("loading session with id "+id);
	},
	
	// drops database
	dropDb: function(){
		var stmt = new air.SQLStatement();
		stmt.addEventListener(air.SQLErrorEvent.ERROR, dojo.hitch(this, "_stmtError", "DB_DROP"));
		stmt.addEventListener(air.SQLEvent.RESULT, dojo.hitch(this, "_stmtResult", "DB_DROP", stmt));
		stmt.sqlConnection = this.conn;
		stmt.text = 'DROP TABLE xRaySessions';

		stmt.execute();
	},
	
	// Creates database
	createDb: function(){
		var d = new dojo.Deferred();
		
		var stmt = new air.SQLStatement();
		stmt.addEventListener(air.SQLErrorEvent.ERROR, function(e){
			d.callback(e);
		});
		
		stmt.addEventListener(air.SQLEvent.RESULT, function(e){
			d.callback(e);
		});
		
		stmt.sqlConnection = this.conn;
		stmt.text = 'CREATE TABLE IF NOT EXISTS xRaySessions ('+
					'id INTEGER PRIMARY KEY AUTOINCREMENT, '+
					'stats_data TEXT, '+
					'comment TEXT, '+
					'author VARCHAR(255), '+
					'created DATETIME )';

		stmt.execute();
		
		return d;
	}
});

dojo.declare("xray.Dialog", dijit.Dialog, {
	_setup: function(){
		// summary: 
		//		stuff we need to do before showing the Dialog for the first
		//		time (but we defer it until right beforehand, for
		//		performance reasons)

		var node = this.domNode;

		if(this.titleBar && this.draggable){
			this._moveable = (dojo.isIE == 6) ?
				new dojo.dnd.TimedMoveable(node, { handle: this.titleBar }) :	// prevent overload, see #5285
				new dojo.dnd.Moveable(node, { handle: this.titleBar, timeout: 0 });
			dojo.subscribe("/dnd/move/stop",this,"_endDrag");
		}else{
			dojo.addClass(node,"dijitDialogFixed"); 
		}
	
		this._underlay = new xray.DialogUnderlay({
			id: this.id+"_underlay",
			"class": dojo.map(this["class"].split(/\s/), function(s){ return s+"_underlay"; }).join(" ")
		});
	
		var underlay = this._underlay;

		this._fadeIn = dojo.fadeIn({
			node: node,
			duration: this.duration,
			onBegin: dojo.hitch(underlay, "show")
		 });
	
		this._fadeOut = dojo.fadeOut({
			node: node,
			duration: this.duration,
			onEnd: function(){
				node.style.visibility="hidden";
				node.style.top = "-9999px";
				underlay.hide();
			}
		 });
	},
	
	show: function(){
		// summary: display the dialog

		if(this.open){ return; }
		
		// first time we show the dialog, there's some initialization stuff to do			
		if(!this._alreadyInitialized){
			this._setup();
			this._alreadyInitialized=true;
		}
		
		if(this._fadeOut.status() == "playing"){
			this._fadeOut.stop();
		}
		
		// AIR doesn't like dojo.connect
		window.nativeWindow.addEventListener(air.NativeWindowBoundsEvent.RESIZING, dojo.hitch(this, "layout"));
		window.nativeWindow.addEventListener(air.NativeWindowBoundsEvent.RESIZE, dojo.hitch(this, "layout"));
		//this._modalconnects.push(dojo.connect(window, "onscroll", this, "layout"));
		//this._modalconnects.push(dojo.connect(window, "onresize", this, "layout"));
		dojo.doc.documentElement.onkeypress = dojo.hitch(this, "_onKey");
		//this._modalconnects.push(dojo.connect(dojo.doc.documentElement, "onkeypress", this, "_onKey"));
		
		dojo.style(this.domNode, {
			opacity:0,
			visibility:""
		});
		
		this.open = true;
		this._loadCheck(); // lazy load trigger

		this._size();
		this._position();

		this._fadeIn.play();

		this._savedFocus = dijit.getFocus(this);

		if(this.autofocus){
			// find focusable Items each time dialog is shown since if dialog contains a widget the 
			// first focusable items can change
			this._getFocusItems(this.domNode);

			// set timeout to allow the browser to render dialog
			setTimeout(dojo.hitch(dijit,"focus",this._firstFocusItem), 50);
		}
	},	
});

dojo.declare(
	"xray.DialogUnderlay",
	dijit.DialogUnderlay,
	{
		layout: function(){
			// summary: Sets the background to the size of the viewport
			//
			// description:
			//	Sets the background to the size of the viewport (rather than the size
			//	of the document) since we need to cover the whole browser window, even
			//	if the document is only a few lines long.

			var viewport = dijit.getViewport();
			var is = this.node.style,
				os = this.domNode.style;

			os.top = viewport.t+53 + "px";
			os.left = viewport.l+8 + "px";
			is.width = viewport.w-16 + "px";
			is.height = viewport.h-106 + "px";

			// process twice since the scroll bar may have been removed
			// by the previous resizing
			var viewport2 = dijit.getViewport();
			if(viewport.w != viewport2.w){ is.width = viewport2.w + "px"; }
			if(viewport.h != viewport2.h){ is.height = viewport2.h + "px"; }
		},
	}
);